﻿using System.Diagnostics;

namespace System
{
    /// <summary>
    /// Provides a set of static methods extending the <see cref="DateTime"/> class.
    /// </summary>
    public static class DateTimeExtensions
    {
        /// <summary>
        /// Subtracts the specified date and time from this <paramref name="instance"/> taking into account the <see cref="System.Globalization.DaylightTime"/>.
        /// </summary>
        /// <param name="instance">The <see cref="DateTime"/> instance assumed to be an universal time if not specified to avoid ambiguous dates.</param>
        /// <param name="value">The <see cref="DateTime"/> to subtract assumed to be an universal time if not specified to avoid ambiguous dates.</param>
        /// <returns>
        /// A <see cref="TimeSpan"/> interval equal to the date and time represented by this <paramref name="instance"/> 
        /// minus the date and time represented by <paramref name="value"/> 
        /// taking into account the <see cref="System.Globalization.DaylightTime"/>.
        /// </returns>
        public static TimeSpan SubtractWithDaylightTime(this DateTime instance, DateTime value)
        {
            return instance
                .AsUniversalTime()
                .ToUniversalTime()
                .Subtract(value
                .AsUniversalTime()
                .ToUniversalTime());
        }

        /// <summary>
        /// Converts the specified <paramref name="value"/> to local time when its <see cref="DateTime.Kind"/> is <see cref="DateTimeKind.Unspecified"/>.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns>A <see cref="DateTime"/> object whose <see cref="DateTime.Kind"/> property is <see cref="DateTimeKind.Local"/>.</returns>
        internal static DateTime AsLocalTime(this DateTime value)
        {
            return (value.Kind == DateTimeKind.Unspecified)
                ? DateTime.SpecifyKind(value, DateTimeKind.Local)
                : value.ToLocalTime();
        }

        /// <summary>
        /// Converts the specified <paramref name="value"/> to Coordinated Universal Time (UTC) when its <see cref="DateTime.Kind"/> is <see cref="DateTimeKind.Unspecified"/>.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns>A <see cref="DateTime"/> object whose <see cref="DateTime.Kind"/> property is <see cref="DateTimeKind.Utc"/>.</returns>
        internal static DateTime AsUniversalTime(this DateTime value)
        {
            return (value.Kind == DateTimeKind.Unspecified)
                ? DateTime.SpecifyKind(value, DateTimeKind.Utc)
                : value.ToUniversalTime();
        }
    }
}